<?php
/**
 * 响应类
 * 
 * @package Response
 * @author Yucy<yucy1985@gmail.com>
 *
 */
class ResponseHelper extends YucyAbsHelper
{
	protected $headers = array();
	
	protected $headersRaw = array();
	
	protected $httpCode = 200;
	
	protected $isRedirect = false;
	
	private $_isOutput = true;
	
	private $_isSendHeader = true;
	
	private $_content = array();
	
	private static $_instance = null;
	
	public function __construct(){}
	
	public static function factory()
	{
		if (!self::$_instance) self::$_instance = new self;
		return self::$_instance;
	}
	
	/**
	 * 
	 * 设置是否输出
	 * @access Public
	 * @param Bool $flag
	 */
	public function isOutput($flag = true)
	{
		$this->_isOutput = $flag;
	}
	
	
	/**
	 * 
	 * 是否发送头信息
	 * @param bool $flag
	 */
	public function isSendHeader($flag = true)
	{
		$this->_isSendHeader = (bool)$flag;
		return $this;
	}
	
	
	/**
	 * 
	 * 设置要发送的内容
	 * @param string $content
	 * @param string $name
	 */
	public function setContent($content, $name = null)
	{
		if ($name === null || !is_string($name)) 
		{
            $this->_content = array('default' => (string)$content);
        }
        else 
        {
            $this->_content[$name] = (string)$content;
        }

        return $this;
	}
	
	
	/**
	 * 
	 * 输出内容
	 */
	private function _sendContent()
	{
        echo implode('', $this->_content);
	}
	
	
	/**
	 * 
	 * 输出内容
	 * @access Public
	 */
	public function output()
	{
    	$this->_sendContent();
	}
	
	
	/**
	 * 
	 * 发送响应
	 */
	public function send()
	{
		if (!$this->_isOutput) return ;
		
		// 发送头信息
    	$this->sendHeaders();
    	
    	$this->_sendContent();
	}
	
	
	/**
	 * 
	 * 标准化HEADER名称
	 * @access Protected
	 * @param String $name
	 * @return String
	 */
	protected function normalizeHeader($name)
    {
        $filtered = str_replace(array('-', '_'), ' ', (string) $name);
        $filtered = ucwords(strtolower($filtered));
        $filtered = str_replace(' ', '-', $filtered);
        return $filtered;
    }
    
    
    /**
     * 
     * 设置HEADER头
     * @access Public
     * @param String $name
     * @param String $value
     * @param Boolean $replace
     * @return Response
     */
    public function setHeader($name, $value, $replace = false)
    {
    	$this->canSendHeaders(false);
    	$name  = $this->normalizeHeader($name);
        $value = (string)$value;

        if ($replace)
        {
            foreach ($this->headers as $key => $header) 
            {
                if ($name == $header['name']) unset($this->headers[$key]);
            }
        }

        $this->headers[] = array('name' => $name, 'value' => $value, 'replace' => $replace);

        return $this;
    }
    
    
    /**
     * 
     * 获取HEADER头
     * @access Public
     * @return Array
     */
    public function getHeaders()
    {
    	return $this->headers;
    }
    
    
    /**
     * 
     * 清空
     * @access Public
     * @param String $name
     */
	public function clearHeader($name)
    {
        if (!count($this->headers))
        {
            return $this;
        }

        foreach ($this->headers as $index => $header) 
        {
            if ($name == $header['name']) unset($this->headers[$index]);
        }

        return $this;
    }
    
    
	public function setRawHeader($value)
    {
        $this->canSendHeaders(true);
        if ('Location' == substr($value, 0, 8)) 
        {
            $this->isRedirect = true;
        }
        $this->headersRaw[] = (string)$value;
        return $this;
    }
    
    
	public function getRawHeaders()
    {
        return $this->headersRaw;
    }

    
    public function clearRawHeaders()
    {
        $this->headersRaw = array();
        return $this;
    }
    
    
    /**
     * 
     * 检查是否可以发送HEADER
     * @access Public
     * @param Boolean $throw
     * @return Boolean
     */
 	public function canSendHeaders($throw = false)
    {
        $flag = headers_sent($file, $line);
        if ($flag && $throw) throw_exception('HEADERS ALREADY SEND IN' . $file . ', LINE ' . $line, 21);

        return !$flag;
    }
    
    
    /**
     * 
     * 设置HTTP状态码
     * @access Public
     * @param Int $code
     * @return Response
     */
	public function setHttpCode($code)
    {
        if (!is_int($code) || (100 > $code) || (599 < $code)) 
        {
           throw_exception('Invalid HTTP code', 22);
        }
        
        $this->isRedirect = ((300 <= $code) && (307 >= $code)) ? true : false;

        $this->httpCode = $code;
        
        return $this;
    }

    
    /**
     * 取 HTTP code
     * @access Public
     * @return Int
     */
    public function getHttpCode()
    {
        return $this->httpCode;
    }
    
    
    /**
     * 
     * 发送HEADER信息
     */
	public function sendHeaders()
    {
        if (count($this->headersRaw) || count($this->headers) || (200 != $this->httpCode)) 
        	$this->canSendHeaders(true);

        $http_code_sent = false;

        foreach ($this->headersRaw as $header) 
        {
            if (!$http_code_sent && $this->httpCode) 
            {
                header($header, true, $this->httpCode);
                $http_code_sent = true;
            }
            else 
            {
                header($header);
            }
        }

        foreach ($this->headers as $header)
        {
            if (!$http_code_sent && $this->httpCode) 
            {
                header($header['name'] . ': ' . $header['value'], $header['replace'], $this->httpCode);
                $http_code_sent = true;
            } 
            else 
            {
                header($header['name'] . ': ' . $header['value'], $header['replace']);
            }
        }

        if (!$http_code_sent) 
        {
            header('HTTP/1.1 ' . $this->httpCode);
            $http_code_sent = true;
        }

        return $this;
    }
    
    
    /**
     * 
     * 设置COOKIE
     * @param string $name
     * @param string $value
     * @param string $expire
     * @param string $path
     * @param string $domain
     * @param string $secure
     * @param bool $httponly
     */
    public function setCookie($name, $value = null, $expire = null, $path = null, $domain = null, $secure = null, $httponly = null)
    {
    	setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
    	
    	return $this;
    }
}